package com.question.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.question.constant.QuestionConstant;
import com.question.constant.RedisKeyConstant;
import com.question.context.BaseContext;
import com.question.exception.QuestionNotFoundException;
import com.question.mapper.*;
import com.question.pojo.dto.*;
import com.question.pojo.dto.QuestionPageDTO;
import com.question.pojo.entity.*;
import com.question.pojo.result.PageResult;
import com.question.pojo.vo.*;
import com.question.service.IQuestionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import com.question.utils.RedisUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class IQuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {

    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private QuestionBlanksMapper questionBlanksMapper;
    @Autowired
    private QuestionChoicesMapper questionChoicesMapper;
    @Autowired
    private QuestionCategoriesMapper questionCategoriesMapper;
    @Autowired
    private UserFavoriteMapper userFavoriteMapper;
    @Autowired
    private QuestionStatisticsMapper questionStatisticsMapper;
    @Autowired
    private UserWrongQuestionMapper userWrongQuestionMapper;
    @Autowired
    private UserAnswerMapper userAnswerMapper;
    @Autowired
    private ChatClient chatClient;

    @Override
    public PageResult listPage(QuestionPageDTO questionPageDTO) {

        //String key = RedisKeyConstant.REDIS_USER_LISTPAGE_KEY + questionPageDTO.hashCode();

        /*List<QuestionPageVO> cacheList = redisUtil.getCacheList(key);
        if (cacheList != null && !cacheList.isEmpty()){
            log.info("redis命中，获取缓存数据！！！！！");
            Page cachePage = (Page) cacheList;
            return new PageResult(cachePage.getTotal(),cachePage.getResult());
        }*/

        PageHelper.startPage(questionPageDTO.getPageNum(), questionPageDTO.getPageSize());

        List<QuestionPageVO> questionList = questionMapper.listPage(questionPageDTO);

        // 存入redis 设置过期时间为2小时
        /*redisUtil.setCacheList(key,questionList);
        redisUtil.expire(key,2, TimeUnit.HOURS);*/

//        Page page = (Page) questionList;

        PageInfo<QuestionPageVO> page = new PageInfo<>(questionList);

        return new PageResult(page.getTotal(),page.getList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<UserQuestionVO> listAllQuestions(UserQuestionDTO questionDTO) {
        //先查询出满足条件的题目
        List<UserQuestionVO> questionList = questionMapper.listAllQuestions(questionDTO);
        if (questionList.isEmpty()){
            throw new QuestionNotFoundException();
        }

        // 判断题目是否被当前用户收藏
        // 取出所有的questionId
        List<Integer> questionIds = questionList.stream()
                .map(UserQuestionVO::getQuestionId)
                .collect(Collectors.toList());

        // 用户id
        Long userId = BaseContext.getCurrentId();

        LambdaQueryWrapper<UserFavorite> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(UserFavorite::getUserId,userId)
                .in(UserFavorite::getQuestionId,questionIds);

        List<UserFavorite> favorites = userFavoriteMapper.selectList(wrapper1);
        Map<Integer, Boolean> favoriteMap = favorites.stream()
                .collect(Collectors.toMap(
                        UserFavorite::getQuestionId, // key
                        favorite -> true));          // value

        for (UserQuestionVO question : questionList) {

            //封装分类信息
            QuestionCategories questionCategories = questionCategoriesMapper.selectById(question.getCategoryId());
            question.setQuestionCategories(questionCategories);

            Integer questionId = question.getQuestionId();
            // 判断是选择题还是填空题
            if (question.getQuestionType().equals(QuestionConstant.CHOICE)){
                // 是选择题，获取相关选项
                QueryWrapper<QuestionChoices> wrapper = new QueryWrapper<>();
                wrapper.eq("question_id", questionId);
                List<QuestionChoices> questionChoices = questionChoicesMapper.selectList(wrapper);
                question.setQuestionChoicesList(questionChoices);

            }else {
                // 是填空题，获取相关填空信息
                QueryWrapper<QuestionBlanks> wrapper = new QueryWrapper<>();
                wrapper.eq("question_id",questionId);
                QuestionBlanks questionBlanks = questionBlanksMapper.selectOne(wrapper);
                question.setQuestionBlanks(questionBlanks);
            }

            //根据map设置是否被收藏状态
            Boolean isCollectd = favoriteMap.getOrDefault(questionId, false);
            question.setIsCollected(isCollectd);

            // 统计题目回答次数和正确率
            QuestionStatistics questionStatistics = questionStatisticsMapper
                    .selectOne(new LambdaQueryWrapper<QuestionStatistics>()
                    .eq(QuestionStatistics::getQuestionId, questionId));

            Integer totalAttempts = questionStatistics.getTotalAttempts();
            Integer correctAttempts = questionStatistics.getCorrectAttempts();

            question.setAnswerTotal(totalAttempts);

            double correctRate = 0.0;
            if (totalAttempts > 0){
                correctRate = ((double)correctAttempts / totalAttempts) * 100;
            }
            // 保留两位小数
            question.setCorrectRate(String.format("%.2f%%", correctRate));
        }
        return questionList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public QuestionSubmitVO submitAnswer(QuestionSubmitDTO questionSubmitDTO) {
        QuestionSubmitVO questionSubmitVO = new QuestionSubmitVO();
        // 查询题目信息
        Question question = questionMapper.selectByQuestionId(questionSubmitDTO.getQuestionId());
        if (question == null){
            throw new QuestionNotFoundException();
        }
        // 查询题目统计信息
        QuestionStatistics questionStatistics =
                questionStatisticsMapper.selectOne(
                        new LambdaQueryWrapper<QuestionStatistics>()
                                .eq(QuestionStatistics::getQuestionId, questionSubmitDTO.getQuestionId()));
        Integer totalAttempts = questionStatistics.getTotalAttempts();  // 总回答次数
        Integer correctAttempts = questionStatistics.getCorrectAttempts(); // 正确次数
        totalAttempts++;
        boolean isCorrect = questionSubmitDTO.getSubmitAnswer().equals(question.getAnswer());
        if (isCorrect) {
            // 回答正确 更新题目总回答次数和正确次数
            correctAttempts++;
            questionStatistics.setTotalAttempts(totalAttempts);
            questionStatistics.setCorrectAttempts(correctAttempts);
        } else {
            // 回答错误 更新总次数
            questionStatistics.setTotalAttempts(totalAttempts);
            Long currentUserId = BaseContext.getCurrentId();
            Integer questionId = question.getQuestionId();
            LambdaQueryWrapper<UserWrongQuestions> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserWrongQuestions::getUserId, currentUserId)
                    .eq(UserWrongQuestions::getQuestionId, questionId);
            Long count = userWrongQuestionMapper.selectCount(queryWrapper);

            if (count == 0) {
                UserWrongQuestions userWrongQuestions = UserWrongQuestions.builder()
                        .questionId(questionId)
                        .userId(currentUserId)
                        .build();
                userWrongQuestionMapper.insert(userWrongQuestions);
            }
        }
        UserAnswer userAnswer = UserAnswer.builder()
                .userId(BaseContext.getCurrentId().intValue())
                .questionId(questionSubmitDTO.getQuestionId())
                .build();
        UserAnswer userAnswerVO = userAnswerMapper.getUserAnswer(userAnswer);
        if (userAnswerVO == null){
            userAnswer.setAnswerContent(questionSubmitDTO.getSubmitAnswer());
            userAnswer.setIsCorrect(isCorrect);
            userAnswerMapper.insert(userAnswer);
        }
        questionStatisticsMapper.update(
                questionStatistics,
                new LambdaQueryWrapper<QuestionStatistics>()
                        .eq(QuestionStatistics::getQuestionId, questionStatistics.getQuestionId()));
        questionSubmitVO.setIsCorrect(isCorrect);
        questionSubmitVO.setMessage(isCorrect ? "恭喜你，回答正确" : "回答错误");
        return questionSubmitVO;
    }

    @Override
    public List<WrongQuestionVO> listWrongQuestion() {
        // 获取当前用户的所有错题
        Long userId = BaseContext.getCurrentId();

        List<UserWrongQuestions> wrongQuestions = userWrongQuestionMapper.selectList(
                new LambdaQueryWrapper<UserWrongQuestions>()
                .eq(UserWrongQuestions::getUserId, userId));

        if (wrongQuestions.isEmpty()){
            return Collections.emptyList();
        }

        // 取出问题id
        List<Integer> questionIds = wrongQuestions
                .stream()
                .map(UserWrongQuestions::getQuestionId)
                .collect(Collectors.toList());

        // 获取题目信息
        List<Question> questionList = questionMapper.selectBatchIds(questionIds);

        // 封装为VO
        List<WrongQuestionVO> wrongQuestionVOS = new ArrayList<>();

        for (Question question : questionList) {
            WrongQuestionVO wrongQuestionVO = new WrongQuestionVO();
            BeanUtil.copyProperties(question,wrongQuestionVO);

            wrongQuestionVO.setUserId(userId);

            // 判断是选择题还是填空题
            if (question.getQuestionType().equals(QuestionConstant.CHOICE)){
                // 是选择题，获取相关选项
                QueryWrapper<QuestionChoices> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("question_id", question.getQuestionId());
                List<QuestionChoices> questionChoices = questionChoicesMapper.selectList(wrapper1);
                wrongQuestionVO.setQuestionChoicesList(questionChoices);

            }else {
                // 是填空题，获取相关填空信息
                QueryWrapper<QuestionBlanks> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("question_id",question.getQuestionId());
                QuestionBlanks questionBlanks = questionBlanksMapper.selectOne(wrapper1);
                wrongQuestionVO.setQuestionBlanks(questionBlanks);
            }

            UserAnswer userAnswer = userAnswerMapper.selectOne(new QueryWrapper<UserAnswer>()
                    .eq("user_id", userId)
                    .eq("question_id", question.getQuestionId()));

            // 添加空值检查
            if (userAnswer != null) {
                wrongQuestionVO.setUserAnswer(userAnswer.getAnswerContent());
            } else {
                // 处理没有作答记录的情况
                log.warn("用户 {} 的问题 {} 没有作答记录", userId, question.getQuestionId());
                wrongQuestionVO.setUserAnswer("未作答");
            }

            wrongQuestionVO.setIsCollected(this.isCollected(question));

            QuestionCategories category = questionCategoriesMapper.selectOne(
                    new QueryWrapper<QuestionCategories>().eq("category_id", question.getCategoryId()));
            wrongQuestionVO.setWeight(question.getWeight());
            wrongQuestionVO.setCategoryName(category.getCategoryName());

            wrongQuestionVOS.add(wrongQuestionVO);
        }

        return wrongQuestionVOS;
    }

    @Override
    public List<QuestionCategories> getQuestionCategory() {
        return questionCategoriesMapper.selectList(null);
    }

    @Override
    public AdviceVO getAdvice(Long userId,Boolean retry) {
        AdviceVO adviceVO = new AdviceVO();
        String key = QuestionConstant.REDIS_USER_ADVICE_KEY + userId;
        if (retry){
            redisUtil.deleteObject(key);
        }
        Object cacheObj = redisUtil.getCacheObject(key);
        AdviceVO cacheVO = new AdviceVO();
        log.info("查询缓存:{}", cacheObj);
        if (cacheObj != null){
            if (cacheObj instanceof JSONObject){
                BeanUtil.copyProperties(cacheObj,cacheVO);
                return cacheVO;
            } else if (cacheObj instanceof AdviceVO) {
                return (AdviceVO) cacheObj;
            }
        }
        try {
            List<WrongQuestionVO> wrongQuestionVOS = this.listWrongQuestion();
            Map<String, Double> analyzeData = this.analyzeWrongQuestions(wrongQuestionVOS);
            String prompt = this.buildPrompt(analyzeData);

            String advice = chatClient.prompt()
                    .user(prompt)
                    .call()
                    .content();
            log.info("学习建议生成成功：{}:{}",userId,advice);
            // 正则表达式清理多余符号
            String fullAdvice = this.cleanAiAdviceText(advice);
            adviceVO.setStatus("success");
            adviceVO.setFullAdvice(fullAdvice);
            adviceVO.setAdviceId(UUID.randomUUID().toString());

            redisUtil.setCacheObject(key,adviceVO,24L,TimeUnit.HOURS);
            return adviceVO;
        }catch (Exception e){
            log.error("学习建议生成失败，请稍后再试",e);
            adviceVO.setStatus("failed");
            return adviceVO;
        }
    }

    // 根据题目类型和权重 统计数据
    private Map<String, Double> analyzeWrongQuestions(List<WrongQuestionVO> wrongQuestions) {
        // 按题目类型/分类统计错题数量和权重
        return wrongQuestions.stream()
                .collect(Collectors.groupingBy(
                        WrongQuestionVO::getCategoryName,  // 按分类名称分组
                        Collectors.summingDouble(WrongQuestionVO::getWeight)  // 使用summingDouble计算权重总和
                ));
    }

    public String cleanAiAdviceText(String rawText) {
        // 1. 去除多余的空行（连续两个及以上换行符替换为一个）
        String cleaned = rawText.replaceAll("(\n\\s*)+", "\n");
        // 2. 去除特殊符号（如多余的中文冒号、破折号等）
        cleaned = cleaned.replaceAll("[：\\-#*]+", "");
        // 3. 去除行首行尾空格
        cleaned = cleaned.trim();
        return cleaned;
    }

    // 构造提示词
    private String buildPrompt(Map<String,Double> analyzeData){
        StringBuilder string = new StringBuilder();
        string.append("小易，你现在是一名专业的计算机相关知识专家，请根据以下学习数据分析结果给出针对性的学习建议，尽量快速生成结论返回：");
        analyzeData.forEach((category,weight)->{
            String s = String.format("- %s类题目错误权重: %.2f\n", category, weight);
            string.append(s);
        });
        string.append("请使用中文给出以下建议：1.薄弱环节分析 2.具体改进建议 3.推荐练习方案 （不用说明用于评估的权重等数据）");
        return string.toString();
    }

    // 获取题目详细信息
    private List<UserQuestionVO> getQuestionDetailByIds(List<Integer> questionIds){

        LambdaQueryWrapper<Question> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Question::getQuestionId,questionIds);
        List<Question> questionList = questionMapper.selectList(wrapper);

        List<UserQuestionVO> questionVOList = new ArrayList<>();
        for (Question question : questionList) {
            UserQuestionVO questionVO = new UserQuestionVO();
            BeanUtil.copyProperties(question,questionVO);

            Integer questionId = question.getQuestionId();

            // 判断是选择题还是填空题
            if (question.getQuestionType().equals(QuestionConstant.CHOICE)){
                // 是选择题，获取相关选项
                QueryWrapper<QuestionChoices> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("question_id", questionId);
                List<QuestionChoices> questionChoices = questionChoicesMapper.selectList(wrapper1);
                questionVO.setQuestionChoicesList(questionChoices);

            }else {
                // 是填空题，获取相关填空信息
                QueryWrapper<QuestionBlanks> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("question_id",questionId);
                QuestionBlanks questionBlanks = questionBlanksMapper.selectOne(wrapper1);
                questionVO.setQuestionBlanks(questionBlanks);
            }

            questionVOList.add(questionVO);
        }

        return questionVOList;
    }

    // 判断题目是否被收藏
    private Boolean isCollected(Question question){

        LambdaQueryWrapper<UserFavorite> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(UserFavorite::getUserId,BaseContext.getCurrentId())
                .eq(UserFavorite::getQuestionId,question.getQuestionId());
        UserFavorite userFavorite = userFavoriteMapper.selectOne(wrapper1);
        return userFavorite != null;
    }

}
